package topic

import (
	"context"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/resultx"
	"mall/service/forum/model"
	"mall/service/forum/rpc/internal/svc"
	"mall/service/forum/rpc/types/forum"

	"github.com/volatiletech/null/v8"
	"github.com/zeromicro/go-zero/core/logx"
)

type CreateTopicsLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewCreateTopicsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateTopicsLogic {
	return &CreateTopicsLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *CreateTopicsLogic) CreateTopics(in *forum.TopicsInfo) (*forum.BaseIDResp, error) {
	if in.AuthorId == nil || *in.AuthorId == 0 {
		return nil, resultx.StatusError(resultx.FORUM_TOPIC_AUTHOR_ID_INVALID, "")
	}

	if in.PostContent == nil || len(strings.TrimSpace(*in.PostContent)) == 0 {
		return nil, resultx.StatusError(resultx.FORUM_POST_CONTENT_REQUIRED, "")
	}

	userId := *in.AuthorId
	now := time.Now()
	topic := &model.ForumTopic{
		TopicAuthorID:     userId,
		Title:             strings.TrimSpace(*in.PostContent),
		TopicDate:         now,
		TopicModifiedDate: now,
	}
	post := &model.ForumPost{
		PostAuthorID:     userId,
		PostContent:      strings.TrimSpace(*in.PostContent),
		PostDate:         now,
		PostModifiedDate: now,
	}

	if in.ForumId != nil && *in.ForumId > 0 {
		topic.ForumID = *in.ForumId
		post.ForumID = *in.ForumId
	}
	if in.AuthorNickname != nil && len(strings.TrimSpace(*in.AuthorNickname)) > 0 {
		nickname := strings.TrimSpace(*in.AuthorNickname)
		topic.TopicAuthorNickname = nickname
		post.PostAuthorNickname = nickname
	}
	if in.AuthorAvatar != nil && len(strings.TrimSpace(*in.AuthorAvatar)) > 0 {
		avatar := strings.TrimSpace(*in.AuthorAvatar)
		topic.TopicAuthorAvatar = avatar
		post.PostAuthorAvatar = avatar
	}
	if in.AuthorIP != nil && len(strings.TrimSpace(*in.AuthorIP)) > 0 {
		ip := strings.TrimSpace(*in.AuthorIP)
		topic.TopicAuthorIP = ip
		post.PostAuthorIP = ip
	}
	if in.AuthorRankId != nil && *in.AuthorRankId > 0 {
		topic.TopicAuthorRankID = uint8(*in.AuthorRankId)
		post.PostAuthorRankID = uint8(*in.AuthorRankId)
	}
	if in.AuthorRoleId != nil && *in.AuthorRoleId > 0 {
		topic.TopicAuthorRoleID = uint8(*in.AuthorRoleId)
		post.PostAuthorRoleID = uint8(*in.AuthorRoleId)
	}
	if in.AuthorAnonymous != nil && *in.AuthorAnonymous > 0 {
		topic.TopicAuthorAnonymous = 1
		post.PostAuthorAnonymous = 1
	}
	if in.TopicTitle != nil && len(strings.TrimSpace(*in.TopicTitle)) > 0 {
		topic.Title = strings.TrimSpace(*in.TopicTitle)
	}
	if in.Status != nil {
		topic.TopicStatus = uint8(*in.Status)
		post.PostStatus = uint8(*in.Status)
	}
	if in.CommentStatus != nil {
		post.CommentStatus = uint8(*in.CommentStatus)
	}

	rel := &model.ForumTopicRel{}
	if len(in.Meta) > 0 {
		for _, v := range in.Meta {
			if v.Key == nil || v.Value == nil || len(strings.TrimSpace(*v.Key)) == 0 || len(strings.TrimSpace(*v.Value)) == 0 {
				continue
			}

			rel.Meta = append(rel.Meta, &model.ForumTopicMetum{
				MetaKey:   strings.TrimSpace(*v.Key),
				MetaValue: null.StringFrom(strings.TrimSpace(*v.Value)),
			})
		}
	}

	var thumbnailOrder uint
	var thumbnailId uint64
	var thumbnailUrl string
	if len(in.NewMedia) > 0 {
		for idx, v := range in.NewMedia {
			var url string
			if v.Url != nil && len(*v.Url) > 0 { // 最终网址
				url = *v.Url
			}
			if len(url) == 0 && v.Uri != nil && len(*v.Uri) > 0 { // 临时网址
				url = *v.Uri
			}
			if len(url) == 0 {
				continue
			}

			var thumbnail uint8
			if v.Thumbnail != nil && *v.Thumbnail > 0 {
				thumbnail = uint8(*v.Thumbnail)
			}
			var order uint
			if v.Order != nil {
				order = uint(*v.Order)
			} else {
				order = uint(idx) + globalkey.AttachmentOrderOffset
			}
			var altText string
			if v.AltText != nil && len(*v.AltText) > 0 {
				altText = *v.AltText
			}

			var meta []string
			if v.Name != nil && len(*v.Name) > 0 {
				meta = append(meta, "filename:"+*v.Name)
				if len(altText) == 0 {
					altText = *v.Name
				}
			}
			if v.MetaData != nil && len(*v.MetaData) > 0 {
				meta = append(meta, *v.MetaData)
			}
			if v.MimeType != nil && len(*v.MimeType) > 0 {
				meta = append(meta, "mimeType:"+*v.MimeType)
			}
			metaData := strings.Join(meta, ";")

			var mediaId uint64
			if v.Id != nil && len(*v.Id) > 0 {
				if i, err := strconv.ParseInt(*v.Id, 10, 64); err == nil && i > 0 {
					mediaId = uint64(i)
				}
			}

			media := &model.ForumAttachmentRelationship{
				AttachmentID:        mediaId,
				AttachmentThumbnail: thumbnail,
				AttachmentOrder:     order,
				AttachmentImageURL:  url,
				AttachmentImageAlt:  altText,
				AttachmentImageMeta: metaData,
			}

			rel.Media = append(rel.Media, media)

			if thumbnail > 0 && (len(thumbnailUrl) == 0 || thumbnailOrder > order) {
				thumbnailOrder = order
				thumbnailId = mediaId
				thumbnailUrl = url
			}
		}

		rel.Meta = append(rel.Meta, &model.ForumTopicMetum{
			MetaKey:   "_photo_count",
			MetaValue: null.StringFrom(strconv.FormatInt(int64(len(rel.Media)), 10)),
		})
	}

	if len(thumbnailUrl) > 0 {
		rel.Meta = append(rel.Meta, &model.ForumTopicMetum{
			MetaKey:   "_thumbnail_id",
			MetaValue: null.StringFrom(strconv.FormatUint(thumbnailId, 10)),
		})
		rel.Meta = append(rel.Meta, &model.ForumTopicMetum{
			MetaKey:   "_thumbnail_url",
			MetaValue: null.StringFrom(thumbnailUrl),
		})
	}

	if topic.TopicAuthorAnonymous == 0 && len(topic.Title) > 0 {
		rel.Feed = &model.ForumFeed{
			ForumID:        topic.ForumID,
			AuthorID:       topic.TopicAuthorID,
			AuthorNickname: topic.TopicAuthorNickname,
			AuthorAvatar:   topic.TopicAuthorAvatar,
			AuthorIP:       topic.TopicAuthorIP,
			AuthorRankID:   topic.TopicAuthorRankID,
			AuthorRoleID:   topic.TopicAuthorRoleID,
			Excerpt:        topic.Title,
			ThumbnailID:    thumbnailId,
			ThumbnailURL:   thumbnailUrl,
			Status:         uint8(globalkey.StatusPending),
		}
	}

	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return nil, resultx.StatusError(resultx.DB_ERROR, "")
	}

	rel.Post = post
	err = l.svcCtx.Topic.Insert(l.ctx, tx, topic, rel)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	tx.Commit()

	return &forum.BaseIDResp{
		Id: topic.TopicID,
	}, nil
}
